#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
地图模块

此模块提供用于表示路径规划环境空间的 Map 类。
"""

import numpy as np
from .obstacle import create_obstacle_from_config


class Map:
    """
    用于路径规划的2D环境地图类。
    """
    
    def __init__(self, width, height, obstacles=None):
        """
        使用给定的尺寸和障碍物初始化地图。
        
        参数:
            width (float): 地图宽度
            height (float): 地图高度
            obstacles (list): 障碍物配置列表
        """
        self.width = width
        self.height = height
        self.obstacles = []
        
        # 如果提供了障碍物，则初始化
        if obstacles:
            for obstacle_config in obstacles:
                self.add_obstacle(obstacle_config)
    
    def add_obstacle(self, obstacle_config):
        """
        向地图添加障碍物。
        
        参数:
            obstacle_config (dict): 障碍物的配置
        """
        obstacle = create_obstacle_from_config(obstacle_config)
        self.obstacles.append(obstacle)
        
    def check_collision(self, x, y, radius=0):
        """
        检查带有可选半径的点 (x, y) 是否与任何障碍物碰撞或超出边界。
        
        参数:
            x (float): 点的X坐标
            y (float): 点的Y坐标
            radius (float): 点周围的半径（用于表示机器人）
            
        返回:
            bool: 如果有碰撞则为True，否则为False
        """
        # 检查点（考虑半径）是否在地图边界内
        if (x - radius < 0 or x + radius > self.width or 
            y - radius < 0 or y + radius > self.height):
            return True
        
        # 检查与每个障碍物的碰撞
        for obstacle in self.obstacles:
            if obstacle.check_collision(x, y, radius):
                return True
        
        return False
    
    def is_valid_point(self, x, y, radius=0):
        """
        检查点是否有效（无碰撞且在边界内）。
        这是check_collision的反函数。
        
        参数:
            x (float): 点的X坐标
            y (float): 点的Y坐标
            radius (float): 点周围的半径（用于表示机器人）
            
        返回:
            bool: 如果有效则为True，否则为False
        """
        return not self.check_collision(x, y, radius)
    
    def sample_random_point(self):
        """
        在地图边界内采样随机点。
        
        返回:
            tuple: 采样点的 (x, y) 坐标
        """
        x = np.random.uniform(0, self.width)
        y = np.random.uniform(0, self.height)
        return x, y
    
    def sample_valid_point(self, radius=0, max_attempts=100):
        """
        在地图内采样随机有效点（与障碍物无碰撞）。
        
        参数:
            radius (float): 用于碰撞检测的半径
            max_attempts (int): 最大采样尝试次数
            
        返回:
            tuple: 采样点的 (x, y) 坐标，如果失败则返回 None
        """
        for _ in range(max_attempts):
            x, y = self.sample_random_point()
            if self.is_valid_point(x, y, radius):
                return x, y
        
        return None  # 未能找到有效点
    
    def get_dimensions(self):
        """
        获取地图的尺寸。
        
        返回:
            tuple: 地图的 (宽度, 高度)
        """
        return self.width, self.height 
    
    def get_obstacles(self):
        """
        获取地图中的障碍物列表。
        
        返回:
            list: 障碍物列表
        """
        return self.obstacles 